package com.yunji.framework_template.common.http;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.zip.GZIPInputStream;

import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpConnectionManager;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethodBase;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.log4j.Logger;

import com.yunji.framework_template.common.constant.Constant;
import com.yunji.framework_template.common.util.StringUtil;
import com.yunji.framework_template.common.web.HttpResult;

/**
 * HttpClient工具类(该工具类在某些使用场景下，不能够检测到对方的连接已经断开的情况，会导致请求发送失败)
 * 
 * @author fenglibin
 * @date 2015-2-5
 */
/**
 * @deprecated (使用HttpConnection替代该功能)
 */
@Deprecated
public class CommonsHttpClientUtil {

    private static final Logger                logger = Logger.getLogger(CommonsHttpClientUtil.class);
    private static final HttpConnectionManager connectionManager;

    private static final HttpClient            client;
    /** 初使化 **/
    static {

        HttpConnectionManagerParams params = loadHttpConfFromFile();

        connectionManager = new MultiThreadedHttpConnectionManager();

        connectionManager.setParams(params);

        client = new HttpClient(connectionManager);

        client.getHostConfiguration().getParams().setParameter("http.default-headers", getHttpDefaultHeader());
    }

    /**
     * 返回默认的Http Client Header
     * 
     * @throws IOException
     */
    public static List<Header> getHttpDefaultHeader() {
        List<Header> headers = new ArrayList<Header>();
        headers.add(new Header("Cache-Control", "max-age=0"));
        headers.add(new Header("Connection", "keep-alive"));
        return headers;
    }

    /**
     * 初使化连接参数
     * 
     * @return
     */
    private static HttpConnectionManagerParams loadHttpConfFromFile() {
        Properties p = new Properties();
        try {
            p.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("httpConfig.properties"));
        } catch (IOException e) {
            logger.error("找不到 HTTP配置文件：httpConfig.properties", e);
        }

        HttpConnectionManagerParams params = new HttpConnectionManagerParams();
        params.setConnectionTimeout(Integer.parseInt(p.getProperty("http.connection.timeout")));
        params.setSoTimeout(Integer.parseInt(p.getProperty("http.so.timeout")));
        params.setStaleCheckingEnabled(Boolean.parseBoolean(p.getProperty("http.stale.check.enabled")));
        params.setTcpNoDelay(Boolean.parseBoolean(p.getProperty("http.tcp.no.delay")));
        params.setDefaultMaxConnectionsPerHost(Integer.parseInt(p.getProperty("http.default.max.connections.per.host")));
        params.setMaxTotalConnections(Integer.parseInt(p.getProperty("http.max.total.connections")));
        params.setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler(3, false));
        return params;
    }

    /**
     * 发起Post请求，并返回SdkHttpResult对象
     * 
     * @param url 请求的URL地址
     * @param content 发送的内容
     * @return
     * @throws HttpException
     * @throws IOException
     */
    public static HttpResult doPost(String url, String content) throws HttpException, IOException {
        return doPost(url, content, null);

    }

    /**
     * 发起Post请求，并返回SdkHttpResult对象
     * 
     * @param url 请求的URL地址
     * @param content 发送的内容
     * @param header 请求头
     * @return
     * @throws HttpException
     * @throws IOException
     */
    public static HttpResult doPost(String url, String content, Map<String, String> header) throws HttpException,
                                                                                            IOException {
        PostMethod method = new PostMethod(url);
        try {
            addHeader(method, header);
            RequestEntity requestEntity = new ByteArrayRequestEntity(content.getBytes(Constant.CHARSET));

            method.getParams().setCookiePolicy(CookiePolicy.IGNORE_COOKIES);
            method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
                                            new DefaultHttpMethodRetryHandler(0, false));
            method.setRequestEntity(requestEntity);

            int statusCode = client.executeMethod(method);
            String result = getResult(method);
            return new HttpResult(statusCode, result, method.getResponseHeaders());
        } finally {
            method.releaseConnection();
        }
    }

    /**
     * 发起Post请求，并返回SdkHttpResult对象
     * 
     * @param url 请求的URL地址
     * @param param 发送的内容
     * @param header 请求头
     * @return
     * @throws HttpException
     * @throws IOException
     */
    public static HttpResult doPost(String url, Map<String, String> param) throws HttpException, IOException {
        return doPost(url, param, null);
    }

    /**
     * 发起Post请求，并返回SdkHttpResult对象
     * 
     * @param url 请求的URL地址
     * @param param 发送的内容
     * @param header 请求头
     * @return
     * @throws HttpException
     * @throws IOException
     */
    public static HttpResult doPost(String url, Map<String, String> param,
                                    Map<String, String> header) throws HttpException, IOException {
        PostMethod method = new PostMethod(url);
        try {

            addHeader(method, header);

            // 设置参数
            NameValuePair[] data = new NameValuePair[param.size()];
            int index = 0;
            for (Map.Entry<String, String> entry : param.entrySet()) {
                NameValuePair pair = new NameValuePair(entry.getKey(), entry.getValue());
                data[index] = pair;
                index++;
            }

            method.getParams().setCookiePolicy(CookiePolicy.IGNORE_COOKIES);
            method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
                                            new DefaultHttpMethodRetryHandler(0, false));
            method.setRequestBody(data);
            int statusCode = client.executeMethod(method);
            String result = getResult(method);
            return new HttpResult(statusCode, result, method.getResponseHeaders());
        } finally {
            method.releaseConnection();
        }
    }

    /**
     * 给请求增加header
     * 
     * @param method
     * @param header
     */
    private static void addHeader(PostMethod method, Map<String, String> header) {
        if (header != null && header.size() > 0) {
            for (Map.Entry<String, String> entry : header.entrySet()) {
                method.setRequestHeader(entry.getKey(), entry.getValue());
            }
        }
        if (header == null || StringUtil.isEmpty(header.get("Content-Type"))) {// 用户没有设置Content-Type，则使用默认的Content-Type
            method.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

        }
    }

    public static HttpClient getClient() {
        return client;
    }

    /**
     * 通过get方法获取网页内容
     * 
     * @param url 获取内容的URL
     * @param resultWithHeader 响应的内容是否带响应头
     * @return 根据当前的URL，获取到的网页的内容
     * @throws IOException
     * @throws HttpException
     */
    public static HttpResult doGet(String url) throws HttpException, IOException {
        GetMethod method = new GetMethod(url);
        method.setFollowRedirects(true);
        try {
            method.setRequestHeader("Content-Type", "text/html; charset=UTF-8");
            int statusCode = client.executeMethod(method);
            String result = getResult(method);
            return new HttpResult(statusCode, result, method.getResponseHeaders());
        } finally {
            method.releaseConnection();

        }
    }

    private static String getResult(HttpMethodBase method) throws IOException {
        String contentEncoding = null;

        Header header = method.getResponseHeader(Constant.HttpHeader.CONTENT_ENCODING);
        if (header != null) {
            contentEncoding = method.getResponseHeader(Constant.HttpHeader.CONTENT_ENCODING).getValue();
        }
        InputStream inputStream = null;
        if (!StringUtil.isEmpty(contentEncoding) && "gzip".equalsIgnoreCase(contentEncoding)) {
            inputStream = new GZIPInputStream(method.getResponseBodyAsStream());
        } else {
            inputStream = method.getResponseBodyAsStream();
        }

        // 在目标页面情况未知的条件下，不推荐使用getResponseBodyAsString()方法
        // String strGetResponseBody = post.getResponseBodyAsString();
        BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, method.getResponseCharSet()));

        String inputLine = null;

        StringBuilder content = new StringBuilder();
        while ((inputLine = in.readLine()) != null) {
            content.append(inputLine);
            content.append(Constant.LINE_SPLITER);
        }

        in.close();

        return content.toString();
    }
}
